/**
 * 公共状态管理
 * redux + react-redux
 * dva [redux-saga] 或 umi   他们的核心都是基于redux封装
 * mobx
 */
/**
 * redux 是js 应用装容器，提供可预测的状态管理
 * redux使用场景：
 *  在应用的大量地方，都存在大量的状态
 *  应用状态会随着时间的推移而频繁更新
 *  更新该状态的逻辑可能很复杂
 *  中型和大型代码量的应用，很多人协同开发
 * 
 * redux库和工具
 *  redux是一个小型的独立js库，通常和其他几个包一起使用
 *  React-Redux
 *      react-redux是官方库，让react和redux交互，可以从store读取一些state，可以通过dispatch actions来更新store
 *  redux toolkit
 *  redux devtools 扩展
 *      浏览器插件
 */
import {createStore} from 'redux';

// 创建reducer：统一修改公共状态
let initialState = {
    supNum: 10,
    oppNum: 5,
};

const reducer = function reducer(state = initialState, action) {

    // 先克隆state
    state = clone(true, state);

    // state：容器中的公共状态 第一次派发，没有公共状态的时候，我们让其处于初始状态
    // action：每一次派发任务，传递进来的“行为对象”，必须包含一个type属性
    // reducer会基于派发的行为标识修改公共状态。reducer用到的行为标识，一定要和每一次派发时，传递的行为标识对应上
    let { type, payload } = action;
    switch(type) {
        case "SUP":
            state.supNum += payload;
            break;
        case "OPP":
            state.oppNum += payload;
            break;
        default:
    }
    // return的值会替换现有的公共状态
};

const store = createStore(reducer);

export default store;

// 使用store
import { createContext } from 'react';
const Theme = createContext();
export default Theme;

// 往root组件挂载
<Theme.Provider value={{store}}></Theme.Provider>

// 在函数组件中使用
const A = function A() {
    const { store } = useContext(Theme);
    const handleClick = () => {
        const { dispatch } = store;
        dispatch({
            type: 'OPP',
            payload: 10
        })
    }
}

const B = function B() {
    const { store } = useContext(Theme);
    let { supNum, oppNum } = store.getState();

    // redux中state改变视图不会刷新
    let [_, setRandom] = useState(0);
    useEffect(() => {
        const unsubscribe = store.subscribe(() => {
            setRandom(+new Date());
        });
        // unsubscribe() 执行可以把刚才注入到是坚持的方法移除
    }, []);

    return (
        <div>
            <p>{supNum}</p>
            <p>{oppNum}</p>
        </div>
    )
}